'''
该示例通利用scipy库求解一重积分/二重积分/三重积分，利用scipy库求解非线性方程组的解，非线性函数的极值点和极值
(1)对函数f1(x) = sin(sqrt(cos(x)+x^2))在区间[0,1]求一重积分
(2)对函数f2(x,y) = x^2 + y^2在x区间[0,1]和y区间[-1,1]上求二重积分
(3)对函数f3(x,y,z) = x^2 + y^2 + z^2在x区间[0,1]，y区间[-1,1]，z区间[-2,2]上求三重积分
(4)求解非线性方程x^3 + 1.1 * x^2 +0.9 * x - 1.4 = 0，用fsolve()函数求解非线性方程组的解。二分法/牛顿迭代法
(5)对非线性函数exp(x) * cos(2*x)求在区间[0,3]上的极小点
(6)对非线性函数exp(x) * cos(2*x)求在0附近的一个极小点
(7)对非线性多元函数100 * (x_2 - x_1^2)^2 + (1 - x_1)^2求解极小值点和极小值，可用method选择不同的无约束优化算法。
'''
import numpy as np
from scipy.integrate import quad, dblquad, tplquad
from scipy.optimize import fsolve, minimize, fminbound, fmin

f1 = lambda x: np.sin(np.sqrt(np.cos(x)+x**2))   # 定义一重积分的函数 lambda表达式用来定义没有名字的简单函数
l1 = quad(f1, 0, 1)  # 求解一重积分
print(f"一重积分的结果为: {l1[0]}，误差为: {l1[1]}")  # quad返回值是一个元组，第一个元素是积分值，第二个元素是误差
f2 = lambda x, y: x**2 + y**2  # 定义二重积分的函数
l2 = dblquad(f2, 0, 1, -1, 1)  # 求解二重积分；如果积分限是函数形式，可以用lambda表达式
print(f"二重积分的结果为: {l2[0]}，误差为: {l2[1]}")  # dblquad返回值同样是一个元组
f3 = lambda x, y, z: x**2 + y**2 + z**2  # 定义三重积分的函数
l3 = tplquad(f3, 0, 1, -1, 1, -2, 2)  # 求解三重积分
print(f"三重积分的结果为: {l3[0]}，误差为: {l3[1]}")  # tplquad返回值同样是一个元组

f4 = lambda x: x**3 + 1.1 * x**2 + 0.9 * x - 1.4  # 定义非线性方程
solution = fsolve(f4, 0)  # 求解非线性方程，初始猜测值为0
print(f"非线性方程的解为: {solution}") 

f5 = lambda x: np.exp(x) * np.cos(2*x)  # 定义非线性函数
x0 = fminbound(f5, 0, 3)  # 求解非线性函数在区间[0,3]上的极小点
print(f"非线性函数在区间[0,3]上的极小点为: {x0}，对应的函数值为: {f5(x0)}")  # fminbound返回极小点的x值

x1 = fmin(f5, 0)  # 求解非线性函数在0附近的一个极小点,以0作为初始值开始搜索
print(f"（5）中非线性函数在0附近的极小点为: {x1}，对应的函数值为: {f5(x1)}")  # fmin返回极小点的x值

f6 = lambda x: 100*(x[1]-x[0]**2)**2 + (1 - x[0])**2
x2 = minimize(f6,[2.0,2.0])
print(f"（6）中极小值点{x2.x}，极小值为{x2.fun}")